#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <string>
#include <ctime>
#include <cassert>
using namespace std;

#define THREAD_NUM 2
int tickets = 10000;

class ThreadData
{
public:
    ThreadData(const string &s, pthread_mutex_t *pm)
        : name(s), pmutex(pm)
    {
    }
    string name;
    pthread_mutex_t *pmutex;
};

void *getTickets(void *args)
{
    ThreadData *td = (ThreadData *)args;
    while (true)
    {
        pthread_mutex_lock(td->pmutex);
        if (tickets > 0)
        {
            usleep(rand() % 1500);
            printf("%s: %d\n", td->name.c_str(), tickets);
            tickets--;
            pthread_mutex_unlock(td->pmutex);
        }
        else
        {
            pthread_mutex_unlock(td->pmutex);
            break;
        }
        usleep(rand() % 2000);
    }
    delete td;
    return nullptr;
}

// void *getTickets(void *args)
// {
//     ThreadData *td = (ThreadData *)args;
//     while (true)
//     {
//         // 抢占逻辑
//         int n = pthread_mutex_lock(td->pmutex);
//         assert(n == 0);
//         if (tickets > 0)
//         { // 判断的本质也是计算的一种
//             usleep(rand() % 1500);
//             printf("%s: %d\n", td->name.c_str(), tickets);
//             tickets--;
//             n = pthread_mutex_unlock(td->pmutex); // 也可能出现问题
//             assert(n == 0);
//         }
//         else
//         {
//             n = pthread_mutex_unlock(td->pmutex);
//             assert(n == 0);
//             break;
//         }
//         // 抢完票，还需要后续的动作
//         usleep(rand() % 2000);
//     }
//     delete td;
//     return nullptr;
// }

int main()
{
    time_t start = time(nullptr);
    pthread_mutex_t mtx;
    pthread_mutex_init(&mtx, nullptr);
    srand((unsigned long)time(nullptr) ^ getpid() ^ 0x211);
    pthread_t t[THREAD_NUM];
    for (int i = 0; i < THREAD_NUM; i++)
    {
        string name = "thread ";
        name += to_string(i + 1);
        ThreadData *td = new ThreadData(name, &mtx);
        pthread_create(t + i, nullptr, getTickets, (void *)td);
    }
    for (int i = 0; i < THREAD_NUM; i++)
    {
        pthread_join(t[i], nullptr);
    }
    pthread_mutex_destroy(&mtx);
    time_t end = time(nullptr);
    cout << "cast: " << (int)(end - start) << "S" << endl;
}
//test
// void *threadRoutine(void *arg)
// {
//     // int i = 0;
//     //  int *data = new int[6];
//     //  while (true)
//     //  {
//     //      cout << "new thread: " << (char *)arg << "running" << endl;
//     //      sleep(1);
//     //      // int a=100;
//     //      // a/=0;
//     //      data[i] = i;
//     //      if (i++ == 5)
//     //          break;
//     //  }
//     // pthread_exit((void*)11);

//     while (true)
//     {
//         cout << "新线程: " << (char *)arg << " running" << endl;
//         sleep(1);
//     }

//     cout << "new thread quit" << endl;
//     // return (void *)data;
// }

// int global_count = 0;

// void *increment_count(void *unused)
// {
//     for (int i = 0; i < 20000000; i++)
//     {
//         ++global_count;
//     }
//     return nullptr;
// }

// void *thread_run(void *arg)
// {
//     pthread_detach(pthread_self());
//     printf("%s\n",static_cast<char*>(arg));
//     return NULL;
// }

// int main()
// {
//     pthread_t threads[2];
//     for (int i = 0; i < 2; i++)
//     {
//         if (pthread_create(&threads[i], NULL, increment_count, NULL))
//         {
//             std::cerr << "Error creating thread" << std::endl;
//         }
//     }

//     for (int i = 0; i < 2; ++i)
//     {
//         pthread_join(threads[i], NULL);
//     }

//     cout << "Final count: " << global_count << endl;
//     // pthread_t tid;
//     // pthread_create(&tid, nullptr, threadRoutine, (void *)"thread 1 ");
//     // int count = 0;
//     // while (true)
//     // {
//     //     cout << "main线程:"
//     //          << " running... " << endl;
//     //     sleep(1);
//     //     count++;
//     //     if (count >= 5)
//     //         break;
//     // }
//     // pthread_cancel(tid);
//     // cout << "pthread cancel:" << tid << endl;

//     // int *ret = nullptr;
//     // pthread_join(tid, (void **)&ret);
//     // cout << "main thread wait done ... main quit ...: new thead quit : "
//     //      << (long long)ret << "\n ";

//     // for (int i = 0; i < 5; i++)
//     // {
//     //     cout << ret[i] << " ";
//     // }
//     // cout << endl;
//     // while (true)
//     // {
//     //     cout << "main thread runnning" << endl;
//     //     sleep(1);
//     // }
// }